/********************************************************
 *
 * FILE NAME:   smartingeegrecord.cpp
 *
 * DESCRIPTION:
 *  Module with Smarting EEG output file
 *
 ********************************************************/

/********************************************************/
/*              Includes                                */
/********************************************************/
#include "smartingeegrecord.h"

#include <QtQml>
#include <QDebug>

/********************************************************/
/*              Defines                                 */
/********************************************************/

/********************************************************/
/*              Macros                                  */
/********************************************************/

/********************************************************/
/*              Typedefs                                */
/********************************************************/

/********************************************************/
/*              Local Functions Declarations (LOCAL)    */
/********************************************************/

/********************************************************/
/*              Global Variables (GLOBAL/IMPORT)        */
/********************************************************/

/********************************************************/
/*              Local Module Variables (MODULE)         */
/********************************************************/

/********************************************************/
/*              Local File Variables (LOCAL)            */
/********************************************************/

/********************************************************/
/*              Functions Definitions (LOCAL/GLOBAL)    */
/********************************************************/
SmartingEEGRecord::SmartingEEGRecord(QObject *parent) : QObject(parent)
{
}

SmartingEEGRecord::~SmartingEEGRecord()
{
    closeRecord();
    delete _file;
    delete _fileMtx;

    delete _worker;
    delete _workerThread;
}

void SmartingEEGRecord::registerTypes(const char *uri)
{
    qmlRegisterType<SmartingEEGRecord>(uri, 1, 0, "SmartingEEGRecord");
}

bool SmartingEEGRecord::init(int burstLength)
{
    _workerThread = new QThread(this);
    _workerThread->start();

    _worker = new SmartingEEGRecordWorker(*this);
    _worker->moveToThread(_workerThread);

    _maxBurstLength = burstLength;

    for(int i = 0; i < SMARTINGEEGRECORD__NUM_OF_CHANNELS; ++i)
    {
        _inISig[i] = new ISignal(0, burstLength);
    }

    _file = new QFile();
    _fileMtx = new QMutex();

    return true;
}

void SmartingEEGRecord::start()
{
    QMetaObject::invokeMethod(_worker, "_startRecording", Qt::QueuedConnection);
}

SmartingEEGRecordWorker::SmartingEEGRecordWorker(SmartingEEGRecord &context) : QObject(0), _context(context)
{
}

void SmartingEEGRecordWorker::_startRecording()
{
    int &maxBurstLength = _context._maxBurstLength;
    ISignal **inISig = _context._inISig;
    QFile &file = *_context._file;
    QMutex &fileMtx = *_context._fileMtx;

    sample_t data;
    int cnt = 0;

    while(true)
    {
        for(int i = 0; i < SMARTINGEEGRECORD__NUM_OF_CHANNELS; ++i)
        {
            inISig[i]->requestBurst(maxBurstLength);
        }

        fileMtx.lock();
        if(file.isOpen())
        {
            for(int i = 0; i < maxBurstLength; ++i)
            {
                for(int j = 0; j < SMARTINGEEGRECORD__NUM_OF_CHANNELS; ++j)
                {
                    inISig[j]->readInSample();
                    data = (*inISig[j])[0];

                    file.write((char *) &data, sizeof(data));
                }
            }

            if(++cnt == 50)
            {
                cnt = 0;
                file.flush();
            }

            fileMtx.unlock();
        }else
        {
            fileMtx.unlock();

            for(int i = 0; i < maxBurstLength; ++i)
            {
                for(int j = 0; j < SMARTINGEEGRECORD__NUM_OF_CHANNELS; ++j)
                {
                    inISig[j]->readInSample();
                }
            }

            cnt = 0;
        }
    }
}

void SmartingEEGRecord::closeRecord()
{
    _fileMtx->lock();
    if(_file->isOpen())
    {
        _file->close();
    }
    _fileMtx->unlock();
}

bool SmartingEEGRecord::newRecord(const QString &dir, const QString &description)
{
    bool ret;
    QString name("SmartingEEGRecord [" + QDateTime::currentDateTime().toString("yy-MM-dd-hh-mm-ss") + "]");
    QString ext("bin");

    QByteArray delimiter;
    delimiter[0] = 0;

    QDir dirObj;
    dirObj.mkdir(dir);

    closeRecord();

    _fileMtx->lock();
    _file->setFileName(dir + "/" + name + "." + ext);
    ret = _file->open(QFile::WriteOnly);

    if(ret)
    {
        _file->write(description.toUtf8());
        _file->write(delimiter);
        _file->flush();
    }
    _fileMtx->unlock();

    return ret;
}
